a972f869be7eaeca8e214844d0492fd1d5e3bb82,src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java,StaticTypeCheckingSupport,chooseBestMethod,#ClassNode#Collection#ClassNode#,692
Before Change
if (params.length > args.length && ! isVargs(params)) {
// GROOVY-5231
int dist = allParametersAndArgumentsMatchWithDefaultParams(params, args);
if (dist>=0 && !receiver.equals(m.getDeclaringClass())) dist+=getDistance(receiver, m.getDeclaringClass());
if (dist>=0 && dist<bestDist) {
bestChoices.clear();
bestChoices.add(m);
bestDist = dist;
} else if (dist>=0 && dist==bestDist) {
bestChoices.add(m);
}
} else if (params.length == args.length) {
int allPMatch = allParametersAndArgumentsMatch(params, args);
int lastArgMatch = isVargs(params)?lastArgMatchesVarg(params, args):-1;
if (lastArgMatch>=0) lastArgMatch++; // ensure exact matches are preferred over vargs
int dist = allPMatch>=0?Math.max(allPMatch, lastArgMatch):lastArgMatch;
if (dist>=0 && !receiver.equals(m.getDeclaringClass())) dist+=getDistance(receiver, m.getDeclaringClass());
if (dist>=0 && dist<bestDist) {
bestChoices.clear();
bestChoices.add(m);
bestDist = dist;
} else if (dist>=0 && dist==bestDist) {
bestChoices.add(m);
}
} else if (isVargs(params)) {
boolean firstParamMatches = true;
// check first parameters
if (args.length > 0) {
Parameter[] firstParams = new Parameter[params.length - 1];
System.arraycopy(params, 0, firstParams, 0, firstParams.length);
firstParamMatches = allParametersAndArgumentsMatch(firstParams, args) >= 0;
}
if (firstParamMatches) {
// there are three case for vargs
// (1) varg part is left out
if (params.length == args.length + 1) {
if (bestDist > 1) {
bestChoices.clear();
bestChoices.add(m);
bestDist = 1;
}
} else {
// (2) last argument is put in the vargs array
// that case is handled above already
// (3) there is more than one argument for the vargs array
int dist = excessArgumentsMatchesVargsParameter(params, args);
if (dist >= 0 && !receiver.equals(m.getDeclaringClass())) dist++;
// varargs methods must not be preferred to methods without varargs
// for example :
// int sum(int x) should be preferred to int sum(int x, int... y)
After Change
* @return the list of methods which best matches the argument types. It is still possible that multiple
* methods match the argument types.
*/
public static List<MethodNode> chooseBestMethod(final ClassNode receiver, Collection<MethodNode> methods, ClassNode... args) {
if (methods.isEmpty()) return Collections.emptyList();
List<MethodNode> bestChoices = new LinkedList<MethodNode>();
int bestDist = Integer.MAX_VALUE;
ClassNode actualReceiver;
for (MethodNode m : methods) {
actualReceiver = receiver!=null?receiver:m.getDeclaringClass();
// todo : corner case
/*
class B extends A {}
Animal foo(A o) {...}
Person foo(B i){...}
B a = new B()
Person p = foo(b)
*/
Parameter[] params = parameterizeArguments(actualReceiver, m);
if (params.length > args.length && ! isVargs(params)) {
// GROOVY-5231
int dist = allParametersAndArgumentsMatchWithDefaultParams(params, args);
if (dist>=0 && !actualReceiver.equals(m.getDeclaringClass())) dist+=getDistance(actualReceiver, m.getDeclaringClass());
if (dist>=0 && dist<bestDist) {
bestChoices.clear();
bestChoices.add(m);
bestDist = dist;
} else if (dist>=0 && dist==bestDist) {
bestChoices.add(m);
}
} else if (params.length == args.length) {
int allPMatch = allParametersAndArgumentsMatch(params, args);
int lastArgMatch = isVargs(params)?lastArgMatchesVarg(params, args):-1;
if (lastArgMatch>=0) lastArgMatch++; // ensure exact matches are preferred over vargs
int dist = allPMatch>=0?Math.max(allPMatch, lastArgMatch):lastArgMatch;
if (dist>=0 && !actualReceiver.equals(m.getDeclaringClass())) dist+=getDistance(actualReceiver, m.getDeclaringClass());
if (dist>=0 && dist<bestDist) {
bestChoices.clear();
bestChoices.add(m);
bestDist = dist;
} else if (dist>=0 && dist==bestDist) {
bestChoices.add(m);
}
} else if (isVargs(params)) {
boolean firstParamMatches = true;
// check first parameters
if (args.length > 0) {
Parameter[] firstParams = new Parameter[params.length - 1];
System.arraycopy(params, 0, firstParams, 0, firstParams.length);
firstParamMatches = allParametersAndArgumentsMatch(firstParams, args) >= 0;
}
if (firstParamMatches) {
// there are three case for vargs
// (1) varg part is left out
if (params.length == args.length + 1) {
if (bestDist > 1) {
bestChoices.clear();
bestChoices.add(m);
bestDist = 1;
}
} else {
// (2) last argument is put in the vargs array
// that case is handled above already
// (3) there is more than one argument for the vargs array
int dist = excessArgumentsMatchesVargsParameter(params, args);
if (dist >= 0 && !actualReceiver.equals(m.getDeclaringClass())) dist++;
// varargs methods must not be preferred to methods without varargs
// for example :
// int sum(int x) should be preferred to int sum(int x, int... y)